<?php
namespace Liaiyong\Light\Data;

use Liaiyong\Light\Base\Component;
use Liaiyong\Light\Data\DataList;
use Liaiyong\Light\Data\DataObject;
use Liaiyong\Light\Util\Logger;
use Liaiyong\Light\Util\Utility;
use stdClass;

abstract class Data extends Component {
    /**
     * 构造方法
     */
    public function __construct() {
        foreach ($this->properties() as $pro => $def) {
            $this->$pro = $def;
        }
        $this->init();
    }
    /**
     * 设置初始值（兼容处理）
     */
    protected function init() {
    }
    /**
     * 扩展属性
     * @param string $key
     */
    protected function expand($key, $next = array()) {
    }
    /**
     * 返回对象属性映射关系
     * @return array
     */
    public function mapping() {
        return array();
    }
    /**
     * 返回对象所有属性值规则
     * @return array
     */
    public function rules() {
        return array();
    }
    /**
     * 返回规则转换后的值
     * @return array
     */
    public function format($val, $key, $option = array()) {
        return $val;
    }

    public static function blank() {
        return new DataObject();
    }
    /**
     * 根据mapping()方法中的映射属性，将查询结果转换为Data类型输出结果。
     * 允许扩展某些属性。
     * @param object|array $obj
     * @return Data
     */
    public static function parse($obj, $keys = array()) {
        $class = get_called_class();
        $object = new $class;
        $mapping = $object->mapping();
        if(is_object($obj)) {
            foreach ($object->properties() as $pro => $def) {
                // property and property mapping
                $map = array_key_exists($pro, $mapping) ? $mapping[$pro] : false;
                $object->__set($pro, !($map && isset($obj->$map)) ? (isset($obj->$pro) ? $obj->$pro : $def) : $obj->$map);
            }
        } else if(is_array($obj) && !empty($obj)) {
            foreach ($object->properties() as $pro => $def) {
                // property and property mapping
                $map = array_key_exists($pro, $mapping) ? $mapping[$pro] : false;
                $object->__set($pro, !($map && isset($obj[$map])) ? (isset($obj[$pro]) ? $obj[$pro] : $def) : $obj[$map]);
            }
        }
        // 扩展一些属性
        if(!empty($keys)) {
            foreach ($keys as $key => $next) {
                if(is_numeric($key)) {
                    $object->expand($next, array());
                } else {
                    $object->expand($key, $next);
                }
            }
        }
        return $object;
    }
    /**
     * 根据mapping()方法中的映射属性，将查询结果转换为Data类型输出结果。
     * @param object|array $obj
     * @return Data
     */
    public static function parseSimple($obj) {
        $class = get_called_class();
        return $class::parse($obj);
    }
    /**
     * 根据mapping()方法中的映射属性，将查询结果数组转换为Data类型输出结果数组。
     * 允许扩展某些属性。
     * @param array<object|array> $arr
     * @param array $keys
     * @return array<Data>
     */
    public static function parseArray($arr, $keys = array()) {
        $class = get_called_class();
        $objects = array();
        foreach ($arr as $val) {
            $objects[] = $class::parse($val, $keys);
        }
        return $objects;
    }
    /**
     * @param array $arr
     */
    public static function parseArraySimple($arr) {
        $class = get_called_class();
        return $class::parseArray($arr);
    }
    /**
     * @param array|object $list
     * @param int $total
     * @param string $since
     * @param boolean $simple
     */
    public static function parseList($list, $total = 0, $hasNext = false, $since = '', $keys = array()) {
        $class = get_called_class();
        $vlist = new DataList();
        if(is_object($list)) {
            $arr = empty($list->list) ? array() : $list->list;
            $total = empty($list->total) ? count($arr) : $list->total;
            $hasNext = empty($list->hasNext) ? false : true;
            $since = empty($list->since) ? '' : $list->since;
        } else if(is_array($list) && Utility::isAssocArray($list)) {
            $arr = empty($list['list']) ? array() : $list['list'];
            $total = empty($list['total']) ? count($arr) : $list['total'];
            $hasNext = empty($list['hasNext']) ? false : true;
            $since = empty($list['since']) ? '' : $list['since'];
        } else if(is_array($list)) {
            $arr = $list;
        } else {
            $arr = array();
        }
        $vlist->__set('list', $class::parseArray($arr, $keys));
        $vlist->__set('total', empty($total) ? count($arr) : $total);
        $vlist->__set('hasNext', empty($hasNext) ? false : true);
        $vlist->__set('since', empty($since) ? '' : $since);
        return $vlist;
    }
    /**
     * @param array|object $list
     * @param int $total
     * @param string $since
     */
    public static function parseListSimple($list, $total = 0, $hasNext = false, $since = '') {
        $class = get_called_class();
        return $class::parseList($list, $total, $hasNext, $since);
    }
}
// PHP END
